package fun.codedesign.jdk.socket.jmx.rmi;


import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import fun.codedesign.jdk.socket.jmx.javabean.HelloMBean;

/**
 * 调用server的客户端
 *
 * @author zengjian
 * @create 2018-06-12 10:35
 * @since 1.0.0
 */
public class HelloAgentClient {

    public static void main(String[] args) throws Exception {
        // 1. 得到现存mbean的 domain属性
        //URL路径的结尾可以随意指定，但如果需要用Jconsole来进行连接，则必须使用jmxrmi
        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9999/jmxrmi");
        JMXConnector connector = JMXConnectorFactory.connect(url);

        MBeanServerConnection connection = connector.getMBeanServerConnection();
        ObjectName objectName = new ObjectName("jmxBean:name=hello");

        System.out.println("domains...");
        String[] domains = connection.getDomains();
        for (int i = 0, length = domains.length; i < length; i++) {
            System.out.println("domains[" + i + "]:" + domains[i]);
        }
        System.out.println("MBeanCount:" + connection.getMBeanCount());


        // 2. 改变mbean的属性
        // 这里的属性名称大写开头
        connection.setAttribute(objectName, new Attribute("Name", "杭州"));
        connection.setAttribute(objectName, new Attribute("Age", 18));

        String name = (String) connection.getAttribute(objectName, "Name");
        Integer age = (Integer) connection.getAttribute(objectName, "Age");
        System.out.println("Name:" + name + ",Age=" + age);


        // 3. 远程调用服务器，传参数修改属性
        // 3.1 原生代理方式
        HelloMBean proxy = MBeanServerInvocationHandler.newProxyInstance(connection, objectName, HelloMBean.class, false);
        proxy.getTelephone();
        proxy.helloWorld();
        proxy.helloWorld("123");

        // 3.2 反射方式执行
        // 或者采用反射方式执行
        connection.invoke(objectName, "helloWorld", null, null);
        // 最后一个参数指定传参类型
        connection.invoke(objectName, "helloWorld", new String[]{"1234"}, new String[]{"java.lang.String"});
        connection.invoke(objectName, "getTelephone", null, null);

    }

}
